/**
 * 
 */
package com.maohi.software.arii;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author heifara
 * 
 */
public class Console {

	public abstract static class Runnable<T> extends Thread {

		private Object results;

		private Exception exception;

		/**
		 * Executed in background while showing progress bar
		 * 
		 * @return the result. It will be returned to the calling method.
		 * @throws Exception
		 */
		protected abstract T doInBackground() throws Exception;

		public Exception getException() {
			return this.exception;
		}

		public Object getResults() {
			return this.results;
		}

		@Override
		public void run() {
			try {
				this.results = this.doInBackground();
			} catch (final Exception aException) {
				this.exception = aException;
			}
		}
	}

	private static BufferedReader currentReader;
	private static List<BufferedReader> readers = new ArrayList<BufferedReader>();

	private final String prompt;
	private final BufferedReader reader;

	public Console() {
		this.prompt = "Arii";
		this.reader = new BufferedReader(new InputStreamReader(System.in));

		currentReader = this.reader;
		readers.add(currentReader);
	}

	public Console(final String aPrompt) {
		this.prompt = aPrompt;
		this.reader = new BufferedReader(new InputStreamReader(System.in));
		currentReader = this.reader;
		readers.add(currentReader);
	}

	public void close() throws IOException {
		readers.remove(this.reader);

		if (currentReader == this.reader) {
			currentReader = readers.get(readers.size() - 1);
		}
	}

	public Boolean showConfirmMessage(final String aText) throws Exception {
		System.out.println(String.format("%s> %s", this.prompt, aText));
		System.out.print(String.format("%s> [type true/false]", this.prompt));
		return Boolean.parseBoolean(this.reader.readLine());
	}

	public String showInputMessage(final String aText) throws Exception {
		System.out.println(String.format("%s> %s", this.prompt, aText));
		return this.showPrompt();
	}

	public void showMessage(final String aText) {
		System.out.println(String.format("%s> %s", this.prompt, aText));
	}

	@SuppressWarnings("unchecked")
	public <T> T showProgressBar(final Runnable<T> aRunnable) throws Exception {
		aRunnable.start();

		final String[] iText = new String[] { "|", "/", "-", "\\" };
		int iIndex = 0;
		System.out.print(String.format("%s> ", this.prompt));
		while (aRunnable.isAlive()) {
			if (iIndex >= (iText.length - 1)) {
				iIndex = 0;
			} else {
				iIndex++;
			}
			System.out.print(iText[iIndex]);
			System.out.print('\b');
			Thread.sleep(50);
		}
		System.out.println();

		if (aRunnable.getException() != null) {
			throw aRunnable.getException();
		}

		return (T) aRunnable.getResults();
	}

	public String showPrompt() throws Exception {
		while (currentReader != this.reader) {
			Thread.sleep(100);
		}
		System.out.print(String.format("%s> ", this.prompt));
		return this.reader.readLine();
	}

}
